#include <stdio.h>
#include <stdlib.h>

int* get_array()
{
/*栈是由系统自动管理的一个区域,用来保存函数的参数传递以及局部变量的声明(可靠性强,灵活性差)
  就比如函数出栈释放后就不能再对原先函数的参数变量进行操作了
  在堆上分配内存就可以进行自己操作了,但是要自己申请自己释放人为管理  
  可使用malloc指令向系统申请内存,并把这个内存的首地址给你,系统不管你怎么使用,所以需要在前面
  使用类型强转,例如下面*/
  int *a = (int*)malloc(5 * sizeof(int));
  /*这个就是在系统申请一个有20个字节的内存,用(int*)强转之后就只能存int型的数据了*/

    for (int i = 0; i < 5; i++)
    {
        scanf("%d",a+i);
    }
    
    return a;

}

int main(int argc, char const *argv[])
{
    int* num = get_array();
    printf("num储存的地址是:%p\n",num);
    for (int i = 0; i < 5; i++)
    {
        printf("num[%d]的数是:%d\n",i,num[i]);
    }

    free(num);/*释放堆的内存,不是清空内存,只是把内存的状态从这个"内存我在用"改成了"我没在用"并且
    告知系统可以随时使用,并且num的指针也没有清空,还是可以靠这个指针寻找这个地址前后的数据*/
    printf("num储存的地址是:%p\n",num);
     for (int i = 0; i < 5; i++)
    {
        printf("num[%d]的数是:%d\n",i,num[i]);
    }

    num = NULL;/*将指针清空,不让num再指向get_array生成的地址*/
    printf("num储存的地址是:%p\n",num);
     for (int i = 0; i < 5; i++)
    {
        printf("num[%d]的数是:%d\n",i,num[i]);
    }
    /*通过以上操作,可以将原先malloc申请的内存还给系统并将main里面的指针给清空,让这个指针不再指向
    原先申请的地址,但是里面改变的数据是不会清空改变,如果需要清空地址的数据,需要使用另外一个指令进行
    遍历清空*/
    /*并且为了防止重复释放,一般使用下面的代码进行判断释放:
    if(num != NULL)
    {
        free(num);
        num = NULL;
    }
    先判断堆里面的内存有没有被释放,没有被释放就释放*/
    return 0;
}
/*问:函数中返回一个数组,能否在函数外对数组进行操作?
  答:不能,当函数被调用返回时,栈中存储的函数中的数据被释放,而数组被返回的是一个地址,这个地址虽然还能找到之前
  被分配的内存空间,但是因为数据被释放,所以原先数组中的数据以及没了*/
